package com.tinysand.advert.index.impl;

import com.tinysand.advert.index.IndexAware;
import com.tinysand.advert.search.feature.DistrictFeature;
import com.tinysand.advert.utils.CommonUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.stream.Collectors;

/**
 * Created By TINY
 * Create Time 2020/2/27
 **/
@Component
@SuppressWarnings("all")
public class DistrictIndex
        implements IndexAware<String, Set<Long>> {

    // 反向索引 <district, unitId>
    private static Map<String, Set<Long>> districtUnitMap;
    // 正向索引 <unitId, district>
    private static Map<Long, Set<String>> unitDistrictMap;

    static {
        districtUnitMap = new ConcurrentHashMap<>();
        unitDistrictMap = new ConcurrentHashMap<>();
    }

    public boolean match(Long adUnitId,
                         List<DistrictFeature.ProvinceAndCity> districts) {
        if (unitDistrictMap.containsKey(adUnitId)
                && CollectionUtils.isNotEmpty(unitDistrictMap.get(adUnitId))) {
            Set<String> unitDistricts = unitDistrictMap.get(adUnitId);
            List<String> targetDistricts = districts.stream()
                    .map(
                            d -> CommonUtils.stringConcat(
                                    d.getProvince(), d.getCity())
                    ).collect(Collectors.toList());
            return CollectionUtils.isSubCollection(targetDistricts, unitDistricts);
        }
        return false;
    }

    @Override
    public Set<Long> get(String key) { return districtUnitMap.get(key); }

    @Override
    public void add(String key, Set<Long> value) {
        Set<Long> unitIdSet = CommonUtils.getOrCreate(
                key, districtUnitMap, ConcurrentSkipListSet::new);
        unitIdSet.addAll(value);

        for (Long unitId : value) {
            Set<String> districts = CommonUtils.getOrCreate(
                    unitId, unitDistrictMap, ConcurrentSkipListSet::new);
            districts.add(key);
        }
    }

    @Override
    public void update(String key, Set<Long> value) {
        // 不支持更新操作
    }

    @Override
    public void delete(String key, Set<Long> value) {
        Set<Long> unitIdSet = CommonUtils.getOrCreate(
                key, districtUnitMap, ConcurrentSkipListSet::new);

        unitIdSet.removeAll(value);

        for (Long unitId : value) {
            Set<String> districts = CommonUtils.getOrCreate(
                    unitId, unitDistrictMap, ConcurrentSkipListSet::new);
            districts.remove(key);
        }
    }
}
